package org.blitengine.layers
{
	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	/**
	 * Based on an experiment by Andre Michelle.
	 * http://lab.andre-michelle.com/tilemapping
	 * */
	public class TileMapLayer extends Layer
	{
		public var shift:int = 4; // 2 << 5 = 32
		private var rest:int;
		private var cols:int;
		private var map:Array;
		private var tiles:BitmapData;
		private var cut:Rectangle = new Rectangle(0, 0, 16, 16);
		
		public function TileMapLayer(map:Array, tiles:BitmapData, cols:int, shift:int=4)
		{
			super(1);
			this.map = map;
			if(!map)
				throw new Error("map is null");
			this.tiles = tiles;
			this.cols = cols;
			this.shift = shift;
			rest = ( 1 << shift ) - 1;
			cut.width = cut.height = 1 << shift
		}		
		
		override protected function updateLayer(cameraX:Number, cameraY:Number):void
		{
			/**
			 * DOTO: implement dirty rect on bitmapData.
			 **/
			render(cameraX, cameraY);
		}
		
		private function render(px:Number, py:Number):void
		{
			var dpt:Point = new Point();
			
			var rw:int = ( bitmapData.height >> shift ) + 2;
			var cl:int = ( bitmapData.width >> shift ) + 1;
			
			var tx:int = px >> shift;
			var ty:int = py >> shift;
			
			var rx:int = px & rest;
			var ry:int = py & rest;
			
			var dpty:int;
			var tyy:int;
			
			var cutx:int;
			
			var x:int;
			var y:int;
			
			mainLoop: for( y = 0 ; y < rw ; y++ )
			{
				tyy = ty + y;
				dpty = ( y << shift ) - ry;
				
				for( x = 0 ; x <= cl ; x++ )
				{
					if(!map[tyy])
						continue mainLoop;
					cols = map[ tyy ][ x + tx ] - 1;
					
					cut.x = ( cols % 20 ) << shift;
					cut.y = int( cols / 20 ) << shift;
					
					dpt.x = ( x << shift ) - rx;
					dpt.y = dpty;
					
					bitmapData.copyPixels( tiles, cut, dpt );
				}
			}
	}
	}
}